The present invention relates generally to computer systems and more particularly to the management of events in computer systems.
The Microsoft OLE 2.01 protocol provides a standard way for objects to fire events and provides a connection architecture for connecting event sources with event sinks. The event and connection architectures provided by Microsoft OLE 2.01 are in large part achieved by defining xe2x80x9cinterfaces.xe2x80x9d In Microsoft OLE 2.01, an xe2x80x9cinterfacexe2x80x9d is a named set of logically related functions. Each interface lists signatures for a set of functions, but does not provide code for implementing the set of functions; rather, objects provide the code for implementing the functions. Such objects are said to xe2x80x9csupportxe2x80x9d the interfaces for which they provide code.
Microsoft OLE 2.01 specifies a component object model (COM). The component object model is implemented through a set of fundamental application program interface (API) functions and interfaces. The API functions provide for object creation, management and marshalling. A component object is one that complies with certain constraints set forth in COM.
The event architecture enables an event source to source events that are sinked by an event sink. As will be described in more detail below, an event source triggers events on an event sink by calling methods on the event sink. Events are logically grouped into semantically-related event sets, and interfaces are defined for each event set that an event sink wishes to sink. Interfaces are provided to provide a form of registration so that an event sink may register to sink events that are sourced by an event source. The registration occurs on a per-event set basis. The event sink and event source are typically separate processes and may reside on the same machine or on different machines.
The event source exposes connection points to which an event sink may connect. Each connection point is associated with a particular event set and indicates that the event source is ready to source events for the associated event set. A connection point may be connected by multiple connections to multiple event sinks. An event source may have multiple connection points (indicating the willingness of the event source to source multiple instances of event sets). The event source connection point container serves as a container of the connection points. Each connection point is typically implemented as a separate sub-object but need not be. Each connection point is assigned a globally unique identifier (GUID), which is a 128 bit value that uniquely identifies an interface or object.
FIG. 1 is a block diagram showing objects and interfaces supported by the objects that play a central role in the event architecture provided by Microsoft OLE 2.01. In FIG. 1, an event sink 10 is connected to both event source 12 and event source 14. Each of the event sources 12 and 14 is a connection point container that contains respective connection points 16A, 16B and 18A, 18B. Each of the event sources 12 and 14 supports the IConnectionPointContainer interface. The line with a circle attached to one end that is labeled xe2x80x9cIConnectionPointContainerxe2x80x9d serves as a graphical indicator to indicate that the object (i.e., event source 12 or 14) supports the named interface. The IConnectionPointContainer interface is formally defined as:
As is apparent from the above definition, the IConnectionPointContainer interface includes two methods. The first method, the EnumConnectionPoints( ) method enumerates the connection points that are contained within the connection point container. Microsoft OLE 2.01 defines a number of enumerator interfaces and methods that enumerate items so that list of items may be communicated and iterated through. This method is an example of such an enumerator method. The result of calling EnumConnectionPoints is that each of the connection points contained in the event source is enumerated. The FindConnectionPoint( ) method returns a connection point that is associated with a particular interface identifier (IID).
Each event set has an associated instance of an interface that the event sink supports. For example, in FIG. 1, event sink 10 supports a set of events in the ISomeEvents interface. The ISomeEvents interface includes a number of methods that may be called from a connection point to trigger associated events. Events are triggered by calling the associated method in the event set interfaces that the event sink 10 supports. Multiple connection points may call methods in a common event set interface. For example, in FIG. 1, connection point 16A and connection point 18A from event sources 12 and 14, respectively, may trigger calls to methods in the ISomeEvents interface instance that is provided by event sink 10. Likewise, it should be appreciated that an event sink may support multiple instances of event set interfaces. For example, in FIG. 1, the event sink 10 supports instances of both the ISomeEvents interface and the IOtherEvents interface. The event sink 10 supports multiple instances of the IOtherEvents interface. No source identity information is passed on an event invocation. Thus, an event sink must set up a forwarding interface for each source to which it is connected. For example, in FIG. 1 separate forwarding objects 19A and 19B have been registered for the separate instances of the IOtherEvents interface.
Each connection point 16A, 16B, 18A and 18B supports the IConnectionPoint interface. This interface is formally defined as:
As can be seen from the above interface definition, the IConnectionPoint interface supports five methods. The GetConnectionInterface( ) method names the event set interface which the connection point is willing to call on the event sink to trigger events. Thus, for connection point 16A, calling the GetConnectionInterface( ) function returns the IID for the instance of the ISomeEvents interface that is provided by the event sink 10. The GetConnectionPointContainer( ) method allows an event sink or other caller to navigate back to the connection point container that contains the connection point. The Advise( ) method creates an advisory connection with an event sink, and the Unadvise( ) method breaks the connection. The EnumConnections( ) method enumerates the event sinks that are currently connected to the connection point.
FIG. 2 is a flowchart illustrating the steps that are performed by an event sink to establish a connection with an event source and begin the process of firing events. Initially, the event sink obtains an interface pointer for the IConnectionPointContainer interface from the event source to which it seeks to connect Microsoft OLE 2.01 provides the QueryInterface( ) method that returns the interface pointer for a requested interface. The event sink obtains the interface pointer for the IConnectionPointContainer by calling the QueryInterface( ) method on the event source (step 24 in FIG. 2). For the example shown in FIG. 1, the event sink 10 calls QueryInterface( ) on both event source 12 and event source 14 to obtain an interface pointer for the IConnectionPointContainer interface. The event sink 10 then calls the FindConnectionPoint( ) method for each event set that it wishes the event source to source (step 26 in FIG. 2). For example, in FIG. 1, the event sink 10 calls the FindConnectionPoint( ) method twice to locate connection points 16A and 16B for event source 12. Similarly, the event sink 10 calls the FindConnectionPoint( ) method twice to locate connection points 18A and 18B on event source 14.
The connection of the event sink to each of the connection points is completed by calling the Advise( ) method in the IConnectionPoint interface for each of the connection points (step 28 in FIG. 2). In the example shown in FIG. 1, the Advise( ) method in the respective instances of the IConnectionPoint interface supported by connection points 16A, 16B, 18A and 18B is called. Once these connections are realized, the event sources 12 and 14 may fire events through the event set interfaces (step 30 in FIG. 1).
Events are called on a single thread of control in a synchronous fashion to provide a single unbroken-path of execution. Events may be called locally or across process and machine boundaries. Whether the called object is local or remote is largely transparent to the caller due to the mechanisms provided by OLE. Calling threads are blocked until the call returns. The blocking mechanism may vary depending on whether the call is local or remote. One implication of this model is that the responsiveness of invoking the component depends on the ability of the invoked component to return control to the invoking component. This approach is adopted with each of the possible threading models for objects that COM supports. COM supports a single threaded model where all calls into the event sink are synchronized with the message queue for the thread on which the event sink object was created. This approach ensures that the event sink is guaranteed to only be called to process events on a single thread of execution. COM also supports an apartment model where objects created on a thread are guaranteed only to be called on that thread. Thus, the event sinks are guaranteed to be called only on the thread that created the event sink. A final threading model that can support a free threading model where in theory, multiple threads may concurrently call on the event sink. The event sink uses a synchronization mechanism to limit concurrent access to the event sink. The underlying threading models, however, appear to be the same to the caller because the RPC model has been made transparent.
Event sinks and event sources often are not resident on the same machines. Microsoft OLE 2.01 provides a mechanism for the marshalling of method calls so that the calls may be remotely transmitted between a client and a server. A xe2x80x9cclientxe2x80x9d calls methods and a xe2x80x9cserverxe2x80x9d implements methods which are called. In the events context, event sinks and event sources assume the roles of both client and server at various times. When the event sink calls on the IConnectionPointContainer and IConnectionPoint interfaces, the event sink acts as a client and the event source acts as a server. Once the connection is realized and the event source begins making calls on the event sink, the event source acts as the client and the event sink acts as the server.
The marshalling mechanism used in the event architecture allows the client to act as if the server being called exists locally in the process space of the client regardless of whether the server is a separate process running on a distinct machine. The marshalling mechanism enhances conventional RPC to allow the remoting of whole interfaces rather than single procedure calls. FIG. 3 is a block diagram illustrating several of the major components that play a role in the marshalling mechanism that is provided. On the client side, a proxy 36 provides an implementation of the methods of the interface that is being remoted. When the client 32 invokes a method on the proxy 36, the proxy 36 copies all of the in parameters of the method that is being invoked into a single linear buffer and outputs a message containing a pointer to the buffer and meta-data about the method that is being invoked. The proxy 36 supports the IRpcProxyBuffer interface. The proxy manager 38 is responsible for loading and unloading proxies for communication with the server 34. The proxy manager 38 is also responsible for managing the establishment and cleanup of the channel buffer 40. The channel buffer 40 encapsulates knowledge about the underlying transport mechanism used by the transport 41. The central role of the channel buffer 40 is to maintain the connection between the proxy 36 and the stub 42.
The server side includes the stub 42, which takes the buffer that has been filled by the proxy 36 and initiates a call on the intended method on the server 34. The stub 42 also receives out parameters from the server 34 when the server has completed the method invocation. The stub 42 marshalls the out parameters into a linear buffer and passes this linear buffer to the channel buffer 46. The stub 42 supports the IRpcStubBuffer interface. The stub manager 44 handles the freeing of stubs when they are no longer needed. In addition, the stub manager 44 cooperates with the proxy manager 38. The stub manager 44 is responsible for maintaining a list of all stubs which are loaded for a given remote client. The channel buffer 46 communicates with channel buffer 40 to translate the buffer holding the out parameters back to the proxy 36 which unmarshalls the out parameters, etc.
FIG. 4 is a flowchart illustrating the steps that are performed in a method invocation from a client to a server when the client and server exist in different execution contexts. Initially the client 32 calls a method on the proxy 36 (step 50 in FIG. 4). The proxy 36 computes the size of the marshalled data and calls the GetBuffer( ) method of the IRpcChannelBuffer interface that is supported by channel buffer 40 (step 52 in FIG. 4). The GetBuffer( ) method obtains memory for the linear buffer for transmitting the marshalled data to the server 34. The in parameters are then copied into the buffer, and the SendReceive( ) method of the IRpcChannelBuffer interface supported by channel buffer 40 is called to transmit the method call to the server 34 (step 54 in FIG. 4). The proxy thread of execution is blocked awaiting the results of the remote call.
Channel buffer 40 then passes the buffer to the channel buffer 46 on the server side via the transport mechanism 41 (step 56 in FIG. 4). The channel buffer 46 on the server side receives the transmitted buffer from the transport 41 on a thread of execution allocated in the server context by the RPC system and calls the Invoke( ) method on the stub 42 (step 58 in FIG. 4). The thread of execution from the channel buffer 46 is blocked in the stub 42 until the method call returns. The Invoke( ) method is used to invoke a particular method through the stub 42. The stub 42 determines the method being called and sets up the parameters to be passed to the server 34. The stub 42 invokes the desired method on the server 34 using the identical in parameters that were passed from the client 32 (step 60 in FIG. 4). The method is executed on the server 34, and the server returns out parameters to the stub 42 (step 62 in FIG. 4). The stub 42 examines the out parameters and calls the GetBuffer( ) method of the IRpcStubBuffer interface that it supports to allocate a buffer in which to return the out parameters to the client 32 (step 64 in FIG. 4). The out parameters are then copied into the allocated buffer, and the stub 42 calls FreeBuffer( ) method to free the buffer for the in parameters (step 66 in FIG. 4).
Channel buffer 46 on the server side calls transport 41 to send a buffer holding the out parameters back to the client 32 (step 68 in FIG. 4). The channel buffer 46 at the client 32 receives the linear buffer holding the out parameters and passes the linear buffer to the proxy 36 (step 70 in FIG. 4). The buffer is returned as the return from the SendReceive( ) method call that was earlier initiated. The proxy 36 unmarshalls the out parameters that have been transmitted in the buffer and sets up the internal stack for the remote call return. The proxy 36 then returns to the client 32 (step 72 in FIG. 4).
Unfortunately, the event and connection architecture provided by Microsoft OLE 2.01 is also limited in several additional respects which may affect the responsiveness or efficiency of programs that are written in accordance with the model. The architecture is limited in that it does not facilitate bidirectionality of connections such that an event sink may pass back control information that primes, focuses and filters the events which the event sink considers to be of interest. An application interested in sparse events in a rich stream is forced to process all events in the stream. When interest in a set of events changes, an existing event connection must be disconnected and another event connection must be created in order to receive changes. An additional limitation is that this architecture does not support asynchronous event delivery. Events are delivered synchronously. This architecture also suffers from either a lack of responsiveness or the creation of an excess number of threads to ensure responsiveness. In general, the responsiveness of an event source is limited by the ability of the event sink to process events sent from the event source to the event sink in a timely fashion. Thus, if an insufficient number of threads are allocated, responsiveness suffers. Conversely, to guarantee responsiveness, the system must create an excessive number of threads. Another final limitation of this architecture is that it does not efficiently facilitate disparate threading models between an event source and an event sink.
The architecture provided by Microsoft(copyright) OLE 2.01 is also limited in that it does not allow third party objects to create connections. Objects must know a priori to whom they are connected. The connection mechanism is non-polymorphic.
The limitations of the prior art are overcome by the present invention. In accordance with a first aspect of the present invention, a method is practiced in a computer system that has an event source for sourcing events and an event sink for sinking events. Per the method, a method call is initiated to invoke an event on a source thread of control of the event source. The method call is received at an intermediary. The source thread of control is returned so that the source thread of control may resume execution. The method call is then invoked by the intermediary on the event sink on a separate thread that is distinct from the source thread of control.
In accordance with another aspect of the present invention, a method of connecting an event source with an event sink is practiced in a computer system. Per this method, a first connection is established from the event source to the event sink for triggering events by directly invoking events at the event sink. A second connection is established from the event sink to the event source for conveying information regarding invoking events. Thus, a bidirectional connection is established between the event source and the event sink. Identity information is maintained for the bidirectional connection created by the combination of the first connection and the second connection.
In accordance with yet another aspect of the present invention, a method of triggering an event is practiced on a computer system that has an event source for sourcing events and an event sink for sinking events. A method call is initiated to invoke the event from an event source. The method call is delivered to an intermediary who preserves the method call. The method call is asynchronously delivered from the intermediary to the event sink to invoke the event.
In accordance with an additional aspect of the present invention, a third party connector is provided for connecting an event source with an event sink. A connection is created between the event source and the event sink via the third party connector so that events from the source may be sinked to the event sink. An event is then sourced to the event source and passed through the connection to be sinked to the event sink.
In accordance with a further aspect of the present invention, a computer system includes a connection that is created between an event source object that sources an event and an event sink object by a connection point object, a proxy object, and a guardian object. The event sink object adopts a concurrency model for threads. The system also includes a connection point object that calls a method on a proxy object to invoke an event. In response, a marshalled method invocation is passed to the guardian object. The marshalled method is invoked using threads of control provided by the event sink object under its concurrency model asynchronously relative to the calling of the method on the proxy object.
In accordance with another aspect of the present invention, the computer system includes an event source for sourcing events and an event sink for sinking events that have been sourced from the event source. A first connection is provided from the event source to the event sink to facilitate triggering of events of the event sink by direct invocation by the event source. A second connection runs from the event sink to the event source to deliver control information regarding the triggering of events from the event sink to the event source.